﻿#ifndef CONNECTION_H
#define CONNECTION_H

#include <memory>
#include <functional>
#include <cstdint>

#define BUFF_64KB 65535

#include "socket.h"
#include "buffer.h"
#include "any.h"
#include "channel.h"

class EventLoop;
class Socket;

class Buffer;
class Any;

enum class ConStatus
{
    CONNECTING,    // 正在连接
    CONNECTED,     // 连接状态
    DISCONNECTING, // 待关闭状态
    DISCONNECTED   // 关闭状态
};

class Connection;
using ConnectionPtr = std::shared_ptr<Connection>;

class Connection : public std::enable_shared_from_this<Connection>
{
private:
    uint64_t m_conn_id;         // 连接id + 定时器id
    ConStatus m_cstatus;        // 连接状态
    // 事件管理
    EventLoop *m_eloop;         // 事件循环
    bool m_enableInactiveRelease; // 是否开启非活跃连接超时销毁
    // 套接字管理
    int m_sockfd;               // 套接字文件描述符
    Socket m_socket;            // 套接字

    // 事件监控
    Channel m_channel;

    // 缓存区管理
    Buffer m_inBuffer;         // 输入缓冲区
    Buffer m_outBuffer;        // 输出缓冲区

    // 协议上下文管理
    Any m_context;

    // 回调函数管理

    using ConnectCallback = std::function<void(const ConnectionPtr &)>;
    using MessageCallback = std::function<void(const ConnectionPtr &, Buffer *)>;
    using CloseCallback = std::function<void(const ConnectionPtr &)>;
    using AnyCallback = std::function<void(const ConnectionPtr &)>;
    ConnectCallback m_connectCb;
    MessageCallback m_messageCb;
    CloseCallback m_closeCb;
    AnyCallback m_anyCb;
    //Note: 组件内的连接关闭回调--组件内设置的，因为服务器组件内会把所有的连接管理起来，一旦某个连接要关闭
    //就应该从管理的地方移除掉自己的信息
    CloseCallback m_serverCloseCb;

private:
    // 读事件回调
    void handleRead();
    // 写事件回调
    void handleWrite();
    // 关闭事件回调
    void handleClose();
    // 错误事件回调
    void handleError();
    // 任意事件回调
    void handleAny();

    // 发送数据
    void _send(Buffer& buf);

    // NOTE: 在关闭连接时，先处理未处理的数据，再释放
    void _shutDown();    
    // 启动非活跃连接的超时销毁功能
    void _enableInactiveRelease(int sec);
    // 取消非活跃连接的超时销毁功能
    void _disableInactiveRelease();
    // NOTE: 释放连接, 真正的关闭连接
    void _release();
    // 建立连接
    void _establishConnection();

    // 切换协议
    void _upgrade(const Any &context,
                const ConnectCallback &con, const MessageCallback &mes,
                const CloseCallback &clo, const AnyCallback &an);
public:
    Connection(EventLoop *eloop, uint64_t conn_id, int sockfd);
    ~Connection();

    // 设置连接状态
    void setConStatus(ConStatus status);
    // 获取连接状态
    ConStatus getConStatus() const;
    // 判断连接是否连接
    bool isConnected() const;
    // 获取连接id
    uint64_t getConnId() const;
    // 获取套接字文件描述符
    int getSockfd() const;
    // 获取套接字
    Socket &getSocket();
    // 获取事件循环
    EventLoop *getEventLoop();

    // 上下文管理 -------------------------------------
    // 设置上下文
    void setContext(const Any &context);
    // 获取上下文
    Any* getContext();
    // 切换协议
    void upgrade(const Any &context,
                const ConnectCallback &con, const MessageCallback &mes,
                const CloseCallback &clo, const AnyCallback &an);

    // 通信数据交互 -------------------------------------
    // 发送数据
    void send(const char* data, size_t size);



    // 修改连接状态相关的函数 -------------------------------------
    // 关闭连接
    void shutDown();
    // 启动非活跃连接的超时销毁功能
    void enableInactiveRelease(int sec);
    // 取消非活跃连接的超时销毁功能
    void disableInactiveRelease();
    // 释放连接
    void release();
    // 建立连接
    void establishConnection();


    // 设置回调函数 -------------------------------------
    // No thread safe 
    // 设置连接回调函数
    void setConnectCallback(const ConnectCallback &cb);
    // 设置消息回调函数
    void setMessageCallback(const MessageCallback &cb);
    // 设置连接关闭回调
    void setCloseCallback(const CloseCallback &cb);
    // 设置任意事件回调
    void setAnyCallback(const AnyCallback &cb);
    // 设置服务器关闭回调
    void setServerCloseCallback(const CloseCallback &cb);
};

#endif
